<template>
  <div
    class="grid-view__column"
    :class="{
      'grid-view__column--filtered':
        !view.filters_disabled &&
        view.filters.findIndex((filter) => filter.field === field.id) !== -1,
      'grid-view__column--sorted':
        view.sortings.findIndex((sort) => sort.field === field.id) !== -1,
    }"
    :style="{ width: width + 'px' }"
    @mousedown="startDragging($event, field)"
  >
    <div
      class="grid-view__description"
      :class="{ 'grid-view__description--loading': field._.loading }"
    >
      <div class="grid-view__description-icon">
        <i class="fas" :class="'fa-' + field._.type.iconClass"></i>
      </div>
      <div class="grid-view__description-name">
        {{ field.name }}
      </div>
      <div v-if="field.error" class="grid-view__description-icon-error">
        <i v-tooltip="field.error" class="fas fa-exclamation-triangle"></i>
      </div>
      <a
        v-if="!readOnly"
        ref="contextLink"
        class="grid-view__description-options"
        @click="$refs.context.toggle($refs.contextLink, 'bottom', 'right', 0)"
        @mousedown.stop
      >
        <i class="fas fa-caret-down"></i>
      </a>
      <FieldContext
        v-if="!readOnly"
        ref="context"
        :table="table"
        :field="field"
        @update="$emit('refresh', $event)"
        @delete="$emit('refresh')"
      >
        <li v-if="canFilter">
          <a @click="createFilter($event, view, field)">
            <i class="context__menu-icon fas fa-fw fa-filter"></i>
            {{ $t('gridViewFieldType.createFilter') }}
          </a>
        </li>
        <li v-if="getCanSortInView(field)">
          <a @click="createSort($event, view, field, 'ASC')">
            <i class="context__menu-icon fas fa-fw fa-sort-amount-down-alt"></i>
            {{ $t('gridViewFieldType.sortField') }}
            <template v-if="getSortIndicator(field, 0) === 'text'">{{
              getSortIndicator(field, 1)
            }}</template>
            <i
              v-if="getSortIndicator(field, 0) === 'icon'"
              class="fa"
              :class="'fa-' + getSortIndicator(field, 1)"
            ></i>
            <i class="fas fa-long-arrow-alt-right"></i>
            <template v-if="getSortIndicator(field, 0) === 'text'">{{
              getSortIndicator(field, 2)
            }}</template>
            <i
              v-if="getSortIndicator(field, 0) === 'icon'"
              class="fa"
              :class="'fa-' + getSortIndicator(field, 2)"
            ></i>
          </a>
        </li>
        <li v-if="getCanSortInView(field)">
          <a @click="createSort($event, view, field, 'DESC')">
            <i class="context__menu-icon fas fa-fw fa-sort-amount-down"></i>
            {{ $t('gridViewFieldType.sortField') }}
            <template v-if="getSortIndicator(field, 0) === 'text'">{{
              getSortIndicator(field, 2)
            }}</template>
            <i
              v-if="getSortIndicator(field, 0) === 'icon'"
              class="fa"
              :class="'fa-' + getSortIndicator(field, 2)"
            ></i>
            <i class="fas fa-long-arrow-alt-right"></i>
            <template v-if="getSortIndicator(field, 0) === 'text'">{{
              getSortIndicator(field, 1)
            }}</template>
            <i
              v-if="getSortIndicator(field, 0) === 'icon'"
              class="fa"
              :class="'fa-' + getSortIndicator(field, 1)"
            ></i>
          </a>
        </li>
        <li v-if="!field.primary && canFilter">
          <a @click="hide($event, view, field)">
            <i class="context__menu-icon fas fa-fw fa-eye-slash"></i>
            {{ $t('gridViewFieldType.hideField') }}
          </a>
        </li>
      </FieldContext>
      <GridViewFieldWidthHandle
        v-if="includeFieldWidthHandles"
        class="grid-view__description-width"
        :grid="view"
        :field="field"
        :width="width"
        :read-only="readOnly"
        :store-prefix="storePrefix"
      ></GridViewFieldWidthHandle>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import { notifyIf } from '@baserow/modules/core/utils/error'

import FieldContext from '@baserow/modules/database/components/field/FieldContext'
import GridViewFieldWidthHandle from '@baserow/modules/database/components/view/grid/GridViewFieldWidthHandle'
import gridViewHelpers from '@baserow/modules/database/mixins/gridViewHelpers'

export default {
  name: 'GridViewFieldType',
  components: { FieldContext, GridViewFieldWidthHandle },
  mixins: [gridViewHelpers],
  props: {
    table: {
      type: Object,
      required: true,
    },
    view: {
      type: Object,
      required: true,
    },
    field: {
      type: Object,
      required: true,
    },
    includeFieldWidthHandles: {
      type: Boolean,
      required: false,
    },
    readOnly: {
      type: Boolean,
      required: true,
    },
  },
  data() {
    return {
      dragging: false,
    }
  },
  computed: {
    width() {
      return this.getFieldWidth(this.field.id)
    },
    canFilter() {
      const filters = Object.values(this.$registry.getAll('viewFilter'))
      for (const type in filters) {
        if (filters[type].fieldIsCompatible(this.field)) {
          return true
        }
      }
      return false
    },
  },
  beforeCreate() {
    this.$options.computed = {
      ...(this.$options.computed || {}),
      ...mapGetters({
        fieldOptions:
          this.$options.propsData.storePrefix + 'view/grid/getAllFieldOptions',
      }),
    }
  },
  methods: {
    async createFilter(event, view, field) {
      // Prevent the event from propagating to the body so that it does not close the
      // view filter context menu right after it has been opened. This is due to the
      // click outside event that is fired there.
      event.stopPropagation()
      event.preventDefault()
      this.$refs.context.hide()

      try {
        await this.$store.dispatch('view/createFilter', {
          view,
          field,
          values: {
            field: field.id,
          },
        })
        this.$emit('refresh')
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    async createSort(event, view, field, order) {
      // Prevent the event from propagating to the body so that it does not close the
      // view filter context menu right after it has been opened. This is due to the
      // click outside event that is fired there.
      event.stopPropagation()
      event.preventDefault()
      this.$refs.context.hide()

      const sort = view.sortings.find((sort) => sort.field === this.field.id)
      const values = {
        field: field.id,
        order,
      }

      try {
        if (sort === undefined) {
          await this.$store.dispatch('view/createSort', {
            view,
            field,
            values,
          })
        } else {
          await this.$store.dispatch('view/updateSort', {
            sort,
            values,
          })
        }

        this.$emit('refresh')
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    async hide(event, view, field) {
      try {
        await this.$store.dispatch(
          this.storePrefix + 'view/grid/updateFieldOptionsOfField',
          {
            field,
            values: { hidden: true },
            oldValues: { hidden: false },
          }
        )
      } catch (error) {
        notifyIf(error, 'view')
      }
    },
    startDragging(event, field) {
      event.preventDefault()
      this.$emit('dragging', { field, event })
    },
    getSortIndicator(field, index) {
      return this.$registry
        .get('field', field.type)
        .getSortIndicator(field, this.$registry)[index]
    },
    getCanSortInView(field) {
      return this.$registry.get('field', field.type).getCanSortInView(field)
    },
  },
}
</script>

<i18n>
{
  "en": {
    "gridViewFieldType":{
      "createFilter": "Create filter",
      "sortField": "Sort",
      "hideField":"Hide field"
    }
  },
  "fr": {
    "gridViewFieldType":{
      "createFilter": "Définir un filtre",
      "sortField": "Trier",
      "hideField":"Cacher un champ"
    }
  }
}
</i18n>
